﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace RaisingStudio.Data.Expressions
{
    /// <summary>
    /// Operation element.
    /// </summary>
    [Serializable]
    public abstract class OperationElement
    {
        #region Epxression Operation 
        public OperationExpression Equal(object value)
        {
            return new OperationExpression(this, ElementOperator.Equal, value);
        }

        public OperationExpression NotEqual(object value)
        {
            return new OperationExpression(this, ElementOperator.NotEqual, value);
        }

        public OperationExpression Less(object value)
        {
            return new OperationExpression(this, ElementOperator.Less, value);
        }

        public OperationExpression Greater(object value)
        {
            return new OperationExpression(this, ElementOperator.Greater, value);
        }

        public OperationExpression LessOrEqual(object value)
        {
            return new OperationExpression(this, ElementOperator.LessOrEqual, value);
        }

        public OperationExpression GreaterOrEqual(object value)
        {
            return new OperationExpression(this, ElementOperator.GreaterOrEqual, value);
        }

        public OperationExpression IsNull()
        {
            return new OperationExpression(this, ElementOperator.IsNull, null);
        }

        public OperationExpression IsNotNull()
        {
            return new OperationExpression(this, ElementOperator.IsNotNull, null);
        }

        public OperationExpression Like(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                if (value.StartsWith("%") || value.StartsWith("%"))
                {
                    return new OperationExpression(this, ElementOperator.Like, value);
                }
                else
                {
                    return Like(value, MatchOperator.Any);
                }
            }
            else
            {
                return Like(value, MatchOperator.Any);
            }
        }

        public OperationExpression Like(string value, MatchOperator matchOperator)
        {
            string matchValue = null;
            switch (matchOperator)
            {
                case MatchOperator.Any:
                    {
                        matchValue = string.Format("%{0}%", value);
                        break;
                    }
                case MatchOperator.Left:
                    {
                        matchValue = string.Format("{0}%", value);
                        break;
                    }
                case MatchOperator.Right:
                    {
                        matchValue = string.Format("%{0}", value);
                        break;
                    }
            }
            return new OperationExpression(this, ElementOperator.Like, matchValue);
        }

        public OperationExpression NotLike(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                if (value.StartsWith("%") || value.StartsWith("%"))
                {
                    return new OperationExpression(this, ElementOperator.NotLike, value);
                }
                else
                {
                    return NotLike(value, MatchOperator.Any);
                }
            }
            else
            {
                return NotLike(value, MatchOperator.Any);
            }
        }

        public OperationExpression NotLike(string value, MatchOperator matchOperator)
        {
            string matchValue = null;
            switch (matchOperator)
            {
                case MatchOperator.Any:
                    {
                        matchValue = string.Format("%{0}%", value);
                        break;
                    }
                case MatchOperator.Left:
                    {
                        matchValue = string.Format("{0}%", value);
                        break;
                    }
                case MatchOperator.Right:
                    {
                        matchValue = string.Format("%{0}", value);
                        break;
                    }
            }
            return new OperationExpression(this, ElementOperator.NotLike, matchValue);
        }

        public OperationExpression Between(object minValue, object maxValue)
        {
            return new OperationExpression(this, ElementOperator.Between, new object[] { minValue, maxValue });
        }

        public OperationExpression Between(ICollection values)
        {
            if (values != null)
            {
                if (values.Count >= 2)
                {
                    return new OperationExpression(this, ElementOperator.Between, values);
                }
                else
                {
                    throw new ArgumentException("进行 Between 或 NotBetween 时，data 值数组元素个数Not 能小于2。");
                }
            }
            else
            {
                throw new ArgumentNullException("values");
            }
        }

        public OperationExpression NotBetween(object minValue, object maxValue)
        {
            return new OperationExpression(this, ElementOperator.NotBetween, new object[] { minValue, maxValue });
        }

        public OperationExpression NotBetween(ICollection values)
        {
            if (values != null)
            {
                if (values.Count >= 2)
                {
                    return new OperationExpression(this, ElementOperator.NotBetween, values);
                }
                else
                {
                    throw new ArgumentException("进行 Between 或 NotBetween 时，data 值数组元素个数Not 能小于2。");
                }
            }
            else
            {
                throw new ArgumentNullException("values");
            }
        }

        public OperationExpression In(ICollection values)
        {
            if (values != null)
            {
                return new OperationExpression(this, ElementOperator.In, values);
            }
            else
            {
                throw new ArgumentNullException("values");
            }
        }

        public OperationExpression NotIn(ICollection values)
        {
            if (values != null)
            {
                return new OperationExpression(this, ElementOperator.NotIn, values);
            }
            else
            {
                throw new ArgumentNullException("values");
            }
        }
        #endregion
        #region 符Operation 
        public BinaryExpression Plus(OperationElement operationElement)
        {
            return new BinaryExpression(this, BinaryOperator.Plus, operationElement);
        }

        public BinaryExpression Plus(object value)
        {
            return new BinaryExpression(this, BinaryOperator.Plus, new ValueExpression(value));
        }

        public BinaryExpression Minus(OperationElement operationElement)
        {
            return new BinaryExpression(this, BinaryOperator.Minus, operationElement);
        }

        public BinaryExpression Minus(object value)
        {
            return new BinaryExpression(this, BinaryOperator.Minus, new ValueExpression(value));
        }

        public BinaryExpression Multiply(OperationElement operationElement)
        {
            return new BinaryExpression(this, BinaryOperator.Multiply, operationElement);
        }

        public BinaryExpression Multiply(object value)
        {
            return new BinaryExpression(this, BinaryOperator.Multiply, new ValueExpression(value));
        }

        public BinaryExpression Divide(OperationElement operationElement)
        {
            return new BinaryExpression(this, BinaryOperator.Divide, operationElement);
        }

        public BinaryExpression Divide(object value)
        {
            return new BinaryExpression(this, BinaryOperator.Divide, new ValueExpression(value));
        }

        public BinaryExpression Modulo(OperationElement operationElement)
        {
            return new BinaryExpression(this, BinaryOperator.Modulo, operationElement);
        }

        public BinaryExpression Modulo(object value)
        {
            return new BinaryExpression(this, BinaryOperator.Modulo, new ValueExpression(value));
        }
        #endregion

        #region 符重载
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public static OperationExpression operator ==(OperationElement operationElement, object value)
        {
            return new OperationExpression(operationElement, ElementOperator.Equal, value);
        }

        public static OperationExpression operator !=(OperationElement operationElement, object value)
        {
            return new OperationExpression(operationElement, ElementOperator.NotEqual, value);
        }

        public static OperationExpression operator <(OperationElement operationElement, object value)
        {
            return new OperationExpression(operationElement, ElementOperator.Less, value);
        }

        public static OperationExpression operator >(OperationElement operationElement, object value)
        {
            return new OperationExpression(operationElement, ElementOperator.Greater, value);
        }

        public static OperationExpression operator <=(OperationElement operationElement, object value)
        {
            return new OperationExpression(operationElement, ElementOperator.LessOrEqual, value);
        }

        public static OperationExpression operator >=(OperationElement operationElement, object value)
        {
            return new OperationExpression(operationElement, ElementOperator.GreaterOrEqual, value);
        }


        public static BinaryExpression operator +(OperationElement operationElement1, OperationElement operationElement2)
        {
            return new BinaryExpression(operationElement1, BinaryOperator.Plus, operationElement2);
        }

        public static BinaryExpression operator +(OperationElement operationElement, object value)
        {
            return new BinaryExpression(operationElement, BinaryOperator.Plus, new ValueExpression(value));
        }

        public static BinaryExpression operator -(OperationElement operationElement1, OperationElement operationElement2)
        {
            return new BinaryExpression(operationElement1, BinaryOperator.Minus, operationElement2);
        }

        public static BinaryExpression operator -(OperationElement operationElement, object value)
        {
            return new BinaryExpression(operationElement, BinaryOperator.Minus, new ValueExpression(value));
        }

        public static BinaryExpression operator *(OperationElement operationElement1, OperationElement operationElement2)
        {
            return new BinaryExpression(operationElement1, BinaryOperator.Multiply, operationElement2);
        }

        public static BinaryExpression operator *(OperationElement operationElement, object value)
        {
            return new BinaryExpression(operationElement, BinaryOperator.Multiply, new ValueExpression(value));
        }

        public static BinaryExpression operator /(OperationElement operationElement1, OperationElement operationElement2)
        {
            return new BinaryExpression(operationElement1, BinaryOperator.Divide, operationElement2);
        }

        public static BinaryExpression operator /(OperationElement operationElement, object value)
        {
            return new BinaryExpression(operationElement, BinaryOperator.Divide, new ValueExpression(value));
        }

        public static BinaryExpression operator %(OperationElement operationElement1, OperationElement operationElement2)
        {
            return new BinaryExpression(operationElement1, BinaryOperator.Modulo, operationElement2);
        }

        public static BinaryExpression operator %(OperationElement operationElement, object value)
        {
            return new BinaryExpression(operationElement, BinaryOperator.Modulo, new ValueExpression(value));
        }
         #endregion
    }
}
